class Data3D {
    constructor(viewer, opt) {
        this.viewer = viewer;
        this._primitive = undefined;
        this.opt = opt || {};
        this.list = this.opt.list || [];
        this.id = Number((new Date()).getTime() + "" + Number(Math.random() * 1000).toFixed(0));
        this.createDom();
        this.heatmapInstance = h337.create({
            container: document.querySelector(`vis3d-heatmap-${this.id}`)
        });
    }

    update(context, frameState, commandList) {
        var geometry = this.getGeometry(this.distance, this.fov, this.aspect);
        if (!geometry) {
            return;
        }
        if (this._primitive) {
            this._primitive.destroy();
            this._primitive = undefined;
        }

        this._primitive = this.viewer.scene.primitives.add(new Cesium.Primitive({
            geometryInstances: new Cesium.GeometryInstance({
                geometry: this.createGeometry(),
            }),
            appearance: new Cesium.Appearance({
                translucent: true,
                flat: true,
            }),
            asynchronous: false
        }));
        this._primitive.id = "heatmap3d";
        this._primitive.update(context, frameState, commandList);
    }

    createDom() {
        this.dom = window.document.createElement("div");
        this.dom.id = `vis3d-heatmap-${this.id}`;
        this.dom.className = `vis3d-heatmap`;
        this.dom.style.width = this.canvasw + "px";
        this.dom.style.height = this.canvasw + "px";
        this.dom.style.position = "absolute";
        this.dom.style.display = "none";
        let mapDom = window.document.getElementById(this.viewer.container.id);

        mapDom.appendChild(this.dom);
    }

    getGeometry() {
        let opt = this.getGrain();
        let geometry = new Cesium.Geometry({
            attributes: new Cesium.GeometryAttributes({
                position: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.DOUBLE,
                    componentsPerAttribute: 3,
                    values: opt.positions,
                }),
                st: new Cesium.GeometryAttribute({
                    componentDatatype: Cesium.ComponentDatatype.FLOAT,
                    componentsPerAttribute: 2,
                    values: new Float32Array(opt.st)
                })
            }),
            indices: new Uint16Array(opt.indices),
            primitiveType: Cesium.PrimitiveType.TRIANGLES,
            boundingSphere: Cesium.BoundingSphere.fromVertices(opt.positions),
        })
        return geometry;
    }

    // 根据经纬度跨度和canvas的宽高 来计算顶点坐标及顶点法向量
    getGrain() {
        let canvasW = this.canvasW || 200;
        let canvasH = this.canvasW || 200;
        let maxLng = this.rect.maxLng;
        let maxLat = this.rect.maxLat;
        let minLng = this.rect.minLng;
        let minLat = this.rect.minLat;

        const granLng_w = (maxLng - minLng) / canvasW; // 经度粒度
        const granLat_H = (maxLat - minLat) / canvasH; // 经度粒度
        let positions = [];
        let st = [];
        let indices = [];

        let points = [];
        for (let i = 0; i < canvasW; i++) {
            let nowLng = minLng + granLng_w * i;

            for (let j = 0; j < canvasH; j++) {
                let nowLat = minLat + granLat_H * j;
                const value = this.heatmapInstance.getValueAt({
                    x: i,
                    y: j
                });
                let cartesian3 = Cesium.Cartesian3.fromDegrees(nowLng, nowLat, this.baseHeight + value);
                positions.push(cartesian3.x, cartesian3.y, cartesian3.z);
                st.push(i / canvasW, j / canvasH);
                if (j != canvasH - 1 && i != canvasW - 1) {
                    indices.push(i * canvasH + j, i * canvasH + j + 1, (i + 1) * canvasH + j);
                    indices.push((i + 1) * canvasH + j, (i + 1) * canvasH + j + 1, i * canvasH + j + 1);
                }

            }
        }

        return {
            positions: positions,
            st: st,
            indices: indices
        }
    }

    getValueByH337() {

    }


    destroy() {

    }
}